import { _decorator, Component, Enum, Node } from 'cc';
import { UIContianer } from './UIContianer';
import { UIUtils } from './UIUtils';
import { UIManager } from './UIManager';
import { UIWatcher } from './UIWatcher';
import { UIAnimationType } from '../NeedToChange/UIConifig';
import { UIAnimation } from './UIAnimation';
const { ccclass, property } = _decorator;

@ccclass('UIBase')
export class UIBase extends Component {
    //应该有一个容器专门存储查找节点和组件
    protected _uiContainer: UIContianer = new UIContianer();
    //是否在关闭的时候要销毁
    protected _isDestroy: boolean = false;
    get isDestroy() {
        return this._isDestroy;
    }
    set isDestroy(destroy: boolean) {
        this._isDestroy = destroy;
    }

    private _uiName: string = '';
    get uiName() {
        return this._uiName;
    }
    set uiName(uiName: string) {
        this._uiName = uiName;
    }

    //存储监听者
    private _arrWatcher: UIWatcher[] = [];
    @property({ type: Enum(UIAnimationType), displayName: '入场动画', tooltip: '入场退场动画,fade淡入淡出...' })
    animType: UIAnimationType = UIAnimationType.none;
    private _uiAnimation: UIAnimation = null;
    //ui的初始化接口，只初始化一次。第一次打开的时候调用。
    //只写在基类，然后另外再写一个初始化接口让派生类重写。
    //公共的初始化逻辑
    init(...rest: any[]) {
        //UI激活之后，去搜索当前UI的整个节点树，然后把需要关注的存储到当前UI下的uiContainer容器中。
        UIUtils.findNode(this.node, this._uiContainer);
        this._uiAnimation = new UIAnimation(this);
        this.onInit.apply(this, arguments);
    }

    //派生类重写的初始化接口
    onInit(...rest: any[]) {

    }

    //打开接口。
    open(...rest: any[]) {
        //显示出ui
        if (!this.node.active) {
            this.node.active = true;
        }
        //播放入场动画，播放完毕后，在处理每次入场逻辑。
        this._uiAnimation.playAnimtion('open', this.animType, () => {
            //处理每次进来的逻辑。
            this.onEnter.apply(arguments);
        });


    }
    //关闭接口
    close(...rest: any[]) {
        //UI退出（派生类）
        this.onExit.apply(this, arguments);
        this._uiAnimation.playAnimtion('close', this.animType, () => {

            if (this._isDestroy) {
                //删除掉跟当前ui的所有wachter从对应的dep删掉。
                for (let watcher of this._arrWatcher) {
                    watcher.removeSelf();
                }
                this.node.destroy();
                return;
            }
            if (this.node.active) {
                this.node.active = false;
            }
        });

    }

    //每次进来 让派生类重写。
    onEnter(...rest: any[]) {

    }
    //每次退出。
    onExit(...rest: any[]) {

    }

    /**
     * 
     * @param uiName 要打开的ui名字
     * @param isClose 当前ui是否要关闭
     * @param isDestroy 这个ui如果要关闭，是否要销毁
     * @param layerName 挂哪个层
     * @param rest 携带的数据
     */
    openUI(uiName: string, isClose: boolean = false, isDestroy: boolean = false, bundleName?: string, layerName: string = 'Normal', ...rest: any[]) {
        let args = [];
        for (let value of rest) {
            args.push(value);
        }
        // unshift:数组前部插入数据，shift前部删除
        // push                     pop
        if (isClose) {
            let temp = UIUtils.deepClone(args);
            temp.unshift(isDestroy);
            temp.unshift(this.uiName);
            this.closeUI.apply(this, temp);
        }
        //要打开的ui的层跟ui名字，额外的数据。
        bundleName = bundleName || 'UI';
        args.unshift(layerName);
        args.unshift(bundleName);
        args.unshift(uiName);
        UIManager.instance.openUI.apply(UIManager.instance, args);
    }

    closeUI(uiName: string, isDestroy: boolean = false, ...rest: any[]) {
        UIManager.instance.closeUI.apply(UIManager.instance, arguments);
    }

    closeSelf(isDestroy: boolean = false, ...rest: any[]) {
        let args = [];
        args.push(this.uiName);
        for (let value of Array.from(arguments)) {
            args.push(value);
        }
        this.closeUI.apply(this, args);
    }


    getNode(nodeName: string) {
        return this._uiContainer.getNode(nodeName);
    }
    getComp<T>(nodeName: string, compTypeName: string): T {
        return this._uiContainer.getComp(nodeName, compTypeName) as T;
    }
    // 封装事件注册，以后用起来更方便一些。
    addEventListener(eventName: string, nodeName: string, cb: Function) {
        //获取节点
        let node = this.getNode(nodeName);
        if (!node) {
            return;
        }
        node.on(eventName, cb);
    }

    //点击
    addClickEventListener(nodeName: string, cb: Function) {
        this.addEventListener('click', nodeName, cb);
    }
    /**
     * 
     * @param msgName 响应的消息，函数名字
     * @param uiName 响应的ui，如果空字符串或者传递空那么认为所有的ui都会接受到。
     * @param rest 
     */
    sendMsg(msgName: string, uiName: string, ...rest: any[]) {
        UIManager.instance.sendMsg.apply(UIManager.instance, arguments);
    }

    //供派生类重写，触发默认响应。
    handleMsg(...rest: any[]) {

    }


    //绑定回调。
    bindCb(data: object, key: string, cb: Function, target?: any, comp?: Component) {
        target = target || this;
        let watcher = new UIWatcher(data, key, target, cb, comp);
        //存储起来的目的：为了后续如果ui销毁，要把这个watcher从对应dep中删掉。
        this._arrWatcher.push(watcher);
    }


    //绑定组件
    bindComp(data: Object, key: string, comp: Component, target?: any) {
        this.bindCb(data, key, UIUtils.refreshComp, target, comp);
    }
}


